
import ecs, { EcsEntity, EcsWorld } from "ecs-ts";
import { Vect3 } from "../../common/MathUtils";
import { EHeroAttri, EHeroAttriModifyType, EHeroAttriOperationType, FindTargetCondition, HeroActionLogic, HeroAttri, OwnSkill } from "./GpDef";

export namespace Comp {

    @ecs.RegComponentType()
    export class Transform extends ecs.EcsComponent {
        /**位置 */
        @ecs.RegObjProp()
        pos = new Vect3()

        /**朝向 */
        @ecs.RegObjProp()
        orientation = new Vect3(0, 1, 0)

        /**期望动量 */
        @ecs.RegObjProp()
        prefVelocity = new Vect3()

        /**动量 */
        @ecs.RegObjProp()
        velocity = new Vect3()

        /**旋转速度 */
        rotateSpeed = 0.1

        /**移动速度 */
        moveSpeed = 1

        /**半径 */
        radius = 20

        /**身高 */
        height = 100
        /**体宽 */
        width = 50

        static tempVec3 = new Vect3()
        static setPrefVelocityByDirection(transform: Transform, direction: Vect3) {
            Vect3.normalize(this.tempVec3, direction)
            Vect3.set(transform.prefVelocity, Vect3.multiplyScalar(this.tempVec3, this.tempVec3, transform.moveSpeed))
        }

        static angle(transform: Transform) {
            const orientationAngle = Math.atan2(transform.orientation.y, transform.orientation.x) + Math.PI

            return orientationAngle
        }
    }
    @ecs.RegComponentType()
    export class Move extends ecs.EcsComponent {
        /**上次寻路时间 */
        lastFindPathTime = 0
        //强制移动目标位置
        hasForceMoveTargetPos = false
        /**强制移动目标位置 （比目标位置）*/
        @ecs.RegObjProp()
        forceMoveTargetPos = new Vect3()

        /**目标方向 */
        @ecs.RegObjProp()
        targetDirection = new Vect3()

        //有目标位置
        hasMoveTargetPos: boolean = false
        /**目标位置 */
        @ecs.RegObjProp()
        targetPos = new Vect3()

        // gridPath: number[][] = []

        targetEntityId = 0
    }


    /**英雄 */
    @ecs.RegComponentType()
    export class Hero extends ecs.EcsComponent {
        value = 0
    }
    @ecs.RegComponentType()
    export class Bulding extends ecs.EcsComponent {
        value = 0
    }
    /**势力 */
    @ecs.RegComponentType()
    export class Force extends ecs.EcsComponent {
        value = 0

    }

    /**寻路节点 */
    @ecs.RegComponentType()
    export class PfNode extends ecs.EcsComponent { }



    /**行为组件 */
    @ecs.RegComponentType()
    export class HeroAction extends ecs.EcsComponent {
        id = 0;
        /**动作播放中 */
        playing = false

        startTimeMs = 0

        range = 0

        needTarget = false
        /**目标条件列表 */
        targetConditionList: FindTargetCondition[] = []
        /**目标 */
        targetId = 0

        /**搜索范围 */
        findTargetRange = 2000
        /**上次搜索目标时间 */
        lastFindTargetTimeMs = 0
        /**当前搜索目标时间间隔 */
        findTargetInterval = 0
        /**最大搜索目标时间间隔 */
        maxFindTargetInterval = 1000

        duration = 1000
        logicList: HeroActionLogic[] = []

        nextActionId = 0

        /**角度范围内才执行 */
        needAngleDgree = 20

        /**触发该动作的技能Id */
        skillId: number = 0
    }


    /**通用组件 */
    export namespace Common {
        /**定时删除组件 */
        @ecs.RegComponentType()
        export class DistroyTimer extends ecs.EcsComponent {
            /**持续时间 */
            durationMs = 0
            /**create时间 */
            createTimeMs = 0

            static init(entity: EcsEntity, world: EcsWorld, durationMs: number) {
                const comp = entity.component(DistroyTimer)
                comp.durationMs = durationMs;
                comp.createTimeMs = world.elapsedTimeMs;
            }
        }
    }
    /**战斗组件 */
    export namespace Battle {
        @ecs.RegComponentType()
        export class BattleInfo extends ecs.EcsComponent {
            /**当前生命*/
            curHp = 0

            /**是近战 */
            isMelee = true
            /**攻击动画播放中 */
            attAnimPlaying = false
            /**当前攻击已触发 */
            curAttTriggered = false
            /**攻击角度范围 */
            attAngleDgree = 15
            /**上次攻击时间 */
            lastAttTimeMs = 0


            /**弹道速度 */
            bulletSpeed = 500
            /**攻击距离 */
            attRange = 100
            /**索敌范围 */
            findEnemyRange = 1500
            /**攻击目标 */
            attTargetEntityId = 0
            /**开启自动攻击 */
            enabelAutoAtt = false

            /**上次攻击目标 */
            lastAttTargetEntityId = 0
            /**连续攻击单个目标累积次数 */
            attSameTargetCount = 0

            /**上次搜索敌人时间 */
            lastFindEnemyTimeMs = 0
            /**当前搜索敌人时间间隔 */
            findEnemyInterval = 0
            /**最大搜索敌人时间间隔 */
            maxFindEnemyInterval = 1000


        }

        @ecs.RegComponentType()
        export class Attri extends ecs.EcsComponent {
            @ecs.RegObjProp()
            attriMap: { [key: string]: HeroAttri } = {
                [EHeroAttri.hp]: new HeroAttri(EHeroAttri.hp, [{ add: 100, mul: 1 }]),
                [EHeroAttri.atp]: new HeroAttri(EHeroAttri.atp, [{ add: 10, mul: 1 }]),
                [EHeroAttri.attSpeed]: new HeroAttri(EHeroAttri.attSpeed, [{ add: 1, mul: 1 }]),
            }

            static getAttri(comp: Attri, attriId) {
                let attri = comp.attriMap[attriId]
                return attri
            }

            static getEntityAttriValue(entity: EcsEntity, attriId) {
                return this.getValue(entity.component(Attri), attriId)
            }

            static getValue(comp: Attri, attriId) {
                let attri = comp.attriMap[attriId]

                if (!attri) {
                    return 0
                }

                const v = attri.modifyList.reduce(
                    (acc, cur) => {
                        if (!cur) {
                            return acc
                        }
                        return (acc + cur.add) * cur.mul
                    }, 0
                )
                return (v + attri.finalModify.add) * attri.finalModify.mul
            }

            static modify(comp: Attri, attriId, value = 0, operation: EHeroAttriModifyType = EHeroAttriModifyType.set, modifyIndex: number = 0, valueType = EHeroAttriOperationType.add) {
                let attri = comp.attriMap[attriId]
                if (!attri) {
                    return attri
                }
                if (!attri.modifyList[modifyIndex]) {
                    attri.modifyList[modifyIndex] = { add: 0, mul: 1 }
                }
                if (operation == EHeroAttriModifyType.set) {
                    attri.modifyList[modifyIndex][valueType] = value
                } else {
                    attri.modifyList[modifyIndex][valueType] += value
                }
                return attri
            }

            static addFinalModify(comp: Attri, attriId, value = 0, valueIndex = 0) {
                let attri = comp.attriMap[attriId]
                if (!attri) {
                    return attri
                }
                attri.finalModify[valueIndex] += value
                return attri
            }
        }


        /**子弹 */
        @ecs.RegComponentType()
        export class Bullet extends ecs.EcsComponent {
            /**发射者id */
            emmiterId = 0
            /**速度 */
            speed = 0
            /**攻击 */
            atp = 0
            /**所属势力 */
            forceId = 0
            /**最大穿透数量 */
            maxPassThrough = 3
            /**已穿透数量 */
            passThrough = 0
            /**忽略目标Map */
            @ecs.RegObjProp()
            passTargetMap: { [targetEntityId: number]: number } = {}
        }

        /**锁定型子弹 */
        @ecs.RegComponentType()
        export class TargetLocker extends ecs.EcsComponent {
            /**目标 */
            targetEntityId = 0

            /**目标位置 */
            @ecs.RegObjProp()
            targetPos = new Vect3()
        }
        /**飞行子弹 */
        @ecs.RegComponentType()
        export class FlyBullet extends ecs.EcsComponent {
        }
        /**激光 */
        @ecs.RegComponentType()
        export class Ray extends ecs.EcsComponent {
            /**目标 */
            targetEntityId = 0

            /**宽度 */
            width = 200

            /**起始位置 */
            @ecs.RegObjProp()
            startPos = new Vect3()

            /**目标位置 */
            @ecs.RegObjProp()
            targetPos = new Vect3()

            static getCornerWidth(ray: Ray) {
                return Math.abs(ray.startPos.x - ray.targetPos.x)
            }

            static getCornerHeight(ray: Ray) {
                return Math.abs(ray.startPos.y - ray.targetPos.y)
            }
        }


        @ecs.RegComponentType()
        export class OwnSkills extends ecs.EcsComponent {
            @ecs.RegObjProp()
            skills: OwnSkill[] = []

            static sortSkillByPriority(ownSkills: OwnSkills) {
                ownSkills.skills.sort((a, b) => {
                    return b.priority - a.priority
                })
            }
        }


        /**buff组件 */
        @ecs.RegComponentType()
        export class Buff extends ecs.EcsComponent {
            /**配置表id */
            public cfgId: number = 0
            /**发出者id */
            public emiterId: number = 0
            /**buff目标id */
            public targetId: number = 0
            /**buff持续时间(毫秒) */
            public durationMs: number = 0
            /**buff开始时间 */
            public startTimeMs: number = 0
            /**buff间隔 */
            public intervalMs: number = 0
            /**上次触发时间 */
            public lastTriggerTimeMs: number = 0
            /**叠加次数 */
            public stackCount: number = 0
        }


        /**buff容器组件 */
        @ecs.RegComponentType()
        export class BuffContainer extends ecs.EcsComponent {
            /**buffMap,key是SkillType，value是buff实体id */
            @ecs.RegObjProp()
            public buffMap: { [key: number]: number } = {};
            @ecs.RegObjProp()
            public buffList: number[] = [];
        }


        /**存活组件 */
        @ecs.RegComponentType()
        export class Alive extends ecs.EcsComponent {
        }
        /**死亡组件 */
        @ecs.RegComponentType()
        export class Dead extends ecs.EcsComponent {
            public startTimeMs = 0
            public durationMs = 1000

            static setDead(world: EcsWorld, entity: EcsEntity, startTimeMs: number) {
                world.addComponent(entity,Dead).startTimeMs = startTimeMs


            }
        }
    }
}